﻿//-----------------------------------------------------------------------
// <copyright file="WebMessageDelete.cs" company="AFS">
// Copyright (c) AFS. All rights reserved.
//
//    This file is part of Chatbox.
//
//    Chatbox is free software: you can redistribute it and/or modify
//    it under the terms of the GNU Lesser General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    any later version.
//
//    Chatbox is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//    GNU Lesser General Public License for more details.
//
//    You should have received a copy of the GNU Lesser General Public License
//    along with Chatbox. If not, see http://www.gnu.org/copyleft/lesser.html
// </copyright>
//----------------------------------------------------------------------- 

namespace ChatBox.Engine.Web
{
    using System;
    using System.Collections.Generic;
    using System.Net;
    using System.Threading;

    using ChatBox.DomainObjects.ResultData;
    using ChatBox.Interfaces;
    using ChatBox.Utility;

    using DomainObjects.Settings;

    /// <summary>
    /// Class to connect to the web and delete messages
    /// </summary>
    public class WebMessageDelete : IMessageDelete
    {
        #region private

        /// <summary>
        /// repsitory for settings data
        /// </summary>
        private readonly IServerSettingsRepository settingsRepository;

        /// <summary>
        /// Interface to the error log
        /// </summary>
        private readonly ILogger logger;

        /// <summary>
        /// Source for login details
        /// </summary>
        private ILogOnSource logOnSource;
        
        /// <summary>
        /// the server to connect to
        /// </summary>
        private string serverName;

        /// <summary>
        /// The thread used
        /// </summary>
        private Thread thread;

        #endregion

        /// <summary>
        /// Initializes a new instance of the WebMessageDelete class
        /// </summary>
        /// <param name="settingsRepository">the server settings</param>
        /// <param name="logger">the error log</param>
        /// <param name="logOnSource">The source of logon details</param>
        public WebMessageDelete(IServerSettingsRepository settingsRepository, ILogger logger, ILogOnSource logOnSource)
        {
            this.settingsRepository = settingsRepository;
            this.logger = logger;
            this.logOnSource = logOnSource;
        }

        /// <summary>
        /// Notify that messages have been deleted
        /// </summary>
        public event EventHandler<EventArgs<DeleteMessagesDataResult>> Completed;

        /// <summary>
        /// Deelete messages on the server
        /// </summary>
        /// <param name="messageIds">ids of messages to be deleted</param>
        public void DeleteMessages(IList<int> messageIds)
        {
            // launch a thread to do it
            ServerSettingsData serverData = this.settingsRepository.ReadSettings();

            this.serverName = serverData.Server;

            // Data is per-thread to make this re-entrant.
            WebMessageDeleteData data = new WebMessageDeleteData();

            data.FormData.Add("op", "message");
            data.FormData.Add("message", String.Empty);
            data.FormData.Add("message_send", "talk");

            foreach (int id in messageIds)
            {
                data.FormData.Add("deletemsg_" + id, "yup");
                data.MessageIds.Add(id);
            }

            this.thread = new Thread(this.ThreadMain);
            this.thread.IsBackground = true;
            this.thread.Name = "Chatbox message delete thread";

            this.thread.Start(data);
        }

        /// <summary>
        /// The thread procedure
        /// </summary>
        /// <param name="data">the data to the thread</param>
        private void ThreadMain(object data)
        {
            WebMessageDeleteData messageData = data as WebMessageDeleteData;
            if (messageData == null)
            {
                this.OnDeleteFail("no data to message delete thread", null);
                return;
            }

            if (this.logOnSource.LogOnCookie == null)
            {
                this.OnDeleteFail("no logon cookie to message delete thread", null);
                return; 
            }

            Uri postUri = new Uri(this.serverName + "/node/fullpage/chatterlight");

            try
            {
                bool success;
                List<Cookie> cookies = new List<Cookie> { this.logOnSource.LogOnCookie };
                using (HttpWebResponse response = WebHelpers.MultipartFormDataPost(
                    postUri, 
                    EngineConstants.UserAgentString, 
                    messageData.FormData, 
                    cookies))
                {
                    success = (response != null) && (response.StatusCode == HttpStatusCode.OK);
                }

                if (success)
                {
                    this.OnDeleteSuccess(messageData.MessageIds);
                }
                else
                {
                    this.OnDeleteFail("no response", null);
                }
            }
            catch (Exception ex)
            {
                string message;
                if (messageData.MessageIds.Count == 1)
                {
                    message = "delete failed";
                }
                else
                {
                    message = "delete failed for " + messageData.MessageIds.Count + " messages";                    
                }

                this.OnDeleteFail(message, ex);
            }
        }

        /// <summary>
        /// Send a success message
        /// </summary>
        /// <param name="messageIds">Message ids to delete</param>
        private void OnDeleteSuccess(IList<int> messageIds)
        {
            DeleteMessagesDataResult result = new DeleteMessagesDataResult(true, messageIds);
            this.Completed(this, new EventArgs<DeleteMessagesDataResult>(result));
        }

        /// <summary>
        /// Send a failure message
        /// </summary>
        /// <param name="message">the failure message</param>
        /// <param name="ex">the exception</param>
        private void OnDeleteFail(string message, Exception ex)
        {
            if (this.logger != null)
            {
                this.logger.LogException(message, ex);
            }

            if (this.Completed != null)
            {
                DeleteMessagesDataResult result = new DeleteMessagesDataResult(false, message, ex);
                this.Completed(this, new EventArgs<DeleteMessagesDataResult>(result));
            }
        }
    }
}
